package com.dl.mall.controller.user;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.dl.mall.config.alipay.AliPayConfig;
import com.dl.mall.config.alipay.AliPayProperties;
import com.dl.mall.config.satoken.StpUserUtil;
import com.dl.mall.entity.user.Order;
import com.dl.mall.entity.user.OrderInfo;
import com.dl.mall.entity.vo.OrderCartVo;
import com.dl.mall.service.user.CartService;
import com.dl.mall.service.user.OrderService;
import com.dl.mall.utils.RedisUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author DL
 * @create 2022-04-13 17:00
 */
@Controller
@RequestMapping("/callback")
@Api(tags="阿里支付回调类controller")
public class AliPayCallBackController {

    @Resource
    private AliPayProperties aliPayProperties;
    @Resource
    private OrderService orderService;
    @Resource
    private CartService cartService;
    @Resource
    private RedisUtils redisUtils;

    @ApiOperation(value="同步回调",notes = "付款成功再回跳转，且只跳转一次 重定向跳转，浏览器调用，不做跟订单相关的操作")
    @RequestMapping("/returnUrl")
    public String returnUrl(HttpServletRequest request, HttpServletResponse response){
        // 验签
        try {
            boolean verified = verified(request);
            if (verified){// 成功就跳转回去
                String out_trade_no = new String(request.getParameter("out_trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
                System.out.println("同步回调 out_trade_no = " + out_trade_no);
                return "redirect:http://localhost:8080/orderSuccess";
            }
            return "redirect:http://localhost:8080/orderError";
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return "redirect:http://localhost:8080/orderError";
        }
    }

    @ApiOperation(value="异步回调",notes = "支付宝调用，如果没有return success，还会继续调用")
    @RequestMapping("/notifyUrl")
    public String notifyUrl(HttpServletRequest request, HttpServletResponse response){
        // 验签
        try {
            boolean verified = verified(request);
            if (verified){// 成功就跳转回去
                // 商户订单号
                String out_trade_no = new String(request.getParameter("out_trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
                System.out.println("out_trade_no = " + out_trade_no);
                // 支付宝交易号
                String transaction_id = new String(request.getParameter("trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
                System.out.println("transaction_id = " + transaction_id);
                // 交易状态
                String trade_status = new String(request.getParameter("trade_status").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
                System.out.println("trade_status = " + trade_status);

                Order order = orderService.getOrderInfoById(out_trade_no);

                // 判断该订单是否在商户网站已经处理
                // 如果没有处理，根据订单号（out_trade_no）在商户网站进行查询并处理
                // 如果已经处理，则不执行商户的逻辑
                boolean isSuccess = false;
                if (trade_status.equals("TRADE_FINISHED")){
                    // 即时到账普通版。   普通版不支持支付完成后的退款操作，即用户充值完成后，该交易就算是完成了，这笔交易就不能再做任何操作了
                    isSuccess = payUtil(order, out_trade_no);
                }else if (trade_status.equals("TRADE_SUCCESS")){
                    // 即时到账高级版。   这个版本在用户充值完成后，卖家可以执行退款操作进行退款，即该交易还没有彻底完成，卖家还可以修改这笔交易。
                    isSuccess = payUtil(order, out_trade_no);
                }
                if (isSuccess){
                    System.out.println("成功了");
                    return "success";
                }else {
                    System.out.println("失败了");
                    return "fail";
                }
            }
            return "fail";
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return "fail";
        }
    }

    // 工具类
    private boolean payUtil(Order order, String out_trade_no){
        System.out.println("order = " + order);
        boolean orderIsSuccess = false,removeCart = false;
        if (order.getOrderState() != 1){
            // 如果交易状态未完成，则删除购物车并更新交易状态

            List<OrderCartVo> orderCartVoList = orderService.getOrderCartVoById(out_trade_no);
            List<Object> removeList = orderCartVoList.stream().map(OrderCartVo::getSpecsId).collect(Collectors.toList());
            System.out.println("removeList = " + removeList);
            removeCart = cartService.removeCart(order.getUserId(), removeList);

            // 如果删除购物车成功，则更新交易状态
            if (removeCart){
                orderIsSuccess = orderService.modifyOrderById(out_trade_no, 1);
                // 支付成功清除redis
                redisUtils.del("order:" + out_trade_no);
            }
        }
        System.out.println("orderIsSuccess = " + orderIsSuccess);
        System.out.println("removeCart = " + removeCart);

        return removeCart && orderIsSuccess;
    }

    // 验签
    private boolean verified(HttpServletRequest request) throws AlipayApiException {
        Map<String, String[]> requestParams = request.getParameterMap();

        Map<String, String> params = new HashMap<>();
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }

        System.out.println("params = " + params);

        return AlipaySignature.rsaCheckV1(params, aliPayProperties.getPublicKey(), aliPayProperties.getCharset(), aliPayProperties.getSignType());
    }
}
